package blackstar.plugin.monitor.reporter;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import blackstar.agent.event.EventDispatcherSupport;
import blackstar.agent.event.EventListener;
import blackstar.agent.event.StartupEvent;
import blackstar.agent.schedule.ScheduleEvent;
import blackstar.agent.schedule.ScheduleTask;

/**
 * @author raywu (ayufox@gmail.com)
 * 
 */
public class BatchReporterAdapter extends EventDispatcherSupport implements
		ResultReporter, EventListener<StartupEvent>
{
	private final static Log LOGGER = LogFactory
			.getLog(BatchReporterAdapter.class);

	private String scheduleCronExpression = "50 0/10 * * * ?";

	private final Object LOCK = new Object();
	private BatchResultReporter targetBatchResultReporter;
	private long maxBatchSize = 1000L;

	private List<ReportData> datas = new ArrayList<ReportData>();

	public BatchReporterAdapter(BatchResultReporter batchResultReporter)
	{
		super();
		this.targetBatchResultReporter = batchResultReporter;
	}

	public void setMaxBatchSize(long maxBatchSize)
	{
		this.maxBatchSize = maxBatchSize;
	}

	public void startup()
	{
		this.dispatch(new ScheduleEvent(this.scheduleCronExpression,
				new ScheduleTask()
				{
					public void schedule()
					{
						commit();
					}
				}));
	}

	public void report(ReportData data)
	{
		List<ReportData> oldDatas = null;
		synchronized (LOCK)
		{
			this.datas.add(data);
			if (this.datas.size() >= this.maxBatchSize)
			{
				oldDatas = this.datas;
				this.datas = new ArrayList<ReportData>();
			}
		}
		if (oldDatas != null)
		{
			commit(oldDatas);
		}
	}

	public void commit()
	{
		List<ReportData> oldDatas = null;
		synchronized (LOCK)
		{
			oldDatas = this.datas;
			this.datas = new ArrayList<ReportData>();
		}
		commit(oldDatas);
	}

	protected void commit(List<ReportData> datas)
	{
		LOGGER.info("commit batch report data[" + datas.size() + "]");

		try
		{
			this.targetBatchResultReporter.reportBatch(datas);
		} catch (Exception e)
		{
			LOGGER.error("Error When commit batch  datas", e);
		}

		LOGGER.info("commit success");
	}

	public Class[] events()
	{
		return new Class[]
		{ StartupEvent.class };
	}

	public void onEvent(StartupEvent event) throws Exception
	{
		startup();
	}
}
